﻿using GylCSharpUtils.Common.Base.SpecialConverter;
using GylCSharpUtils.Common.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GylCSharpUtils.GSerializer.Utils {

    /// <summary>
    /// 序列化对象标识<br/>
    /// 用于在序列化过程中标识对象位置
    /// </summary>
    public class SerialObjID {

        private readonly ushort[] serialNums;
        private string str;
        private readonly int hash;


        private SerialObjID(ushort[] id) {
            if(id == null || id.Length == 0) id = new ushort[] { 0 };
            this.serialNums = id;
            //this.str = ArrayUtils.ToStr(id,"_");
            //this.hash = str.GetHashCode();
            for(int i = 0; i < id.Length; i++) {
                this.hash ^= id[i].GetHashCode();
            }
        }
        public SerialObjID(ushort id) : this(new ushort[] { id }) {
        }

        /// <summary>
        /// 获取子对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">子对象在父对象中的序号，实际是ushort类型</param>
        /// <returns></returns>
        public SerialObjID Child(int id) {
            var len = this.serialNums.Length;
            var tmp = new ushort[len + 1];
            Array.Copy(this.serialNums, tmp, len);
            tmp[len] = (ushort)id;
            return new SerialObjID(tmp);
        }


        public SerialObjID Parent() {
            var len = this.serialNums.Length - 1;
            if(len == 0) return null;
            var tmp = new ushort[len];
            Array.Copy(this.serialNums, tmp, len);
            return new SerialObjID(tmp);
        }

        public override bool Equals(object obj) {
            if(this == obj) return true;
            if(!(obj is SerialObjID)) return false;
            SerialObjID o = (SerialObjID)obj;
            if(hash != o.hash) return false;
            if(this.serialNums.Length != o.serialNums.Length) return false;
            for(int i = 0; i < serialNums.Length; i++) {
                if(serialNums[i] != o.serialNums[i]) return false;
            }
            return true;
        }

        public override int GetHashCode() {
            return hash;
        }

        public override string ToString() {
            if(str == null) {
                str = ArrayUtils.ToStr(serialNums, "_");
            }
            return str;
        }
    }
}
